package com.linxiao.hrcrm.service.impl;

import java.math.BigDecimal;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.linxiao.hrcrm.domain.*;
import com.linxiao.hrcrm.service.*;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.manager.AdminManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.linxiao.hrcrm.mapper.CrmCustomerSignInMapper;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 客户签卡记录Service业务层处理
 *
 * @author zhoudong
 * @date 2024-01-03
 */
@Service
public class CrmCustomerSignInServiceImpl implements ICrmCustomerSignInService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private CrmCustomerSignInMapper crmCustomerSignInMapper;
    @Resource
    private ICrmWorksiteService crmWorksiteService;
    @Resource
    private ICrmProjectService crmProjectService;
    @Resource
    private AdminManager adminManager;
    @Resource
    private ICrmCustomerSalaryService crmCustomerSalaryService;
    @Resource
    private ICrmCustomerService crmCustomerService;
    @Resource
    private ICrmCustomerProjectService crmCustomerProjectService;

    /**
     * 查询客户签卡记录
     *
     * @param id 客户签卡记录主键
     * @return 客户签卡记录
     */
    @Override
    public CrmCustomerSignIn selectCrmCustomerSignInById(Long id) {
        return crmCustomerSignInMapper.selectCrmCustomerSignInById(id);
    }

    /**
     * 查询客户签卡记录列表
     *
     * @param crmCustomerSignIn 客户签卡记录
     * @return 客户签卡记录
     */
    @Override
    public List<CrmCustomerSignIn> selectCrmCustomerSignInList(CrmCustomerSignIn crmCustomerSignIn) {
        List<CrmCustomerSignIn> crmCustomerSignIns = crmCustomerSignInMapper.selectCrmCustomerSignInList(crmCustomerSignIn);
        if (CollUtil.isNotEmpty(crmCustomerSignIns)) {
            crmCustomerSignIns.parallelStream().forEach(ccs -> {
                CrmCustomer crmCustomer = crmCustomerService.selectCrmCustomerById(ccs.getCustomerId());
                if (crmCustomer != null) {
                    ccs.setCustomerName(crmCustomer.getCustomerName());
                } else {
                    ccs.setCustomerName("未知");
                }
            });
        }
        return crmCustomerSignIns;
    }

    /**
     * 新增客户签卡记录
     *
     * @param crmCustomerSignIn 客户签卡记录
     * @return 结果
     */
    @Override
    public int insertCrmCustomerSignIn(CrmCustomerSignIn crmCustomerSignIn) {
        checkParams(crmCustomerSignIn);
        crmCustomerSignIn.setCreateTime(DateUtils.getNowDate());
        return crmCustomerSignInMapper.insertCrmCustomerSignIn(crmCustomerSignIn);
    }

    /**
     * 参数检验
     * @param crmCustomerSignIn
     */
    private void checkParams(CrmCustomerSignIn crmCustomerSignIn) {
        crmCustomerSignIn.setSignInDate(DateUtils.getNowDate());
        crmCustomerSignIn.setSignInTime(DateUtils.getNowDate());
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 查询客户表
        CrmCustomer customer = crmCustomerService.selectCrmCustomerByMemberId(crmCustomerSignIn.getMchId(), loginUser.getUserId());
        if (customer == null) {
            // 如果客户存在，则新增
            customer = new CrmCustomer();
            customer.setMchId(crmCustomerSignIn.getMchId());
            customer.setCustomerName(loginUser.getUser().getNickName());
            customer.setNickname(loginUser.getUser().getNickName());
            customer.setCustomerType(CrmCustomer.CUSTOMER_TYPE_WORKER);
            customer.setGender(Integer.parseInt(loginUser.getUser().getSex()));
            customer.setPhoneNumber(loginUser.getUser().getPhonenumber());
            customer.setSource("签卡未查询到客户补充");
            crmCustomerService.insertCrmCustomer(customer);
        }
        crmCustomerSignIn.setCustomerId(customer.getId());

        // 查询项目
        CrmProject crmProject = crmProjectService.selectCrmProjectById(crmCustomerSignIn.getProjectId());
        if (crmProject == null) {
            throw new UtilException("项目有误");
        }
        // 获取上下班打卡时间范围
        /*if(StrUtil.isBlank(crmProject.getSignInBegin()) || StrUtil.isBlank(crmProject.getSignInEnd())) {
            throw new UtilException("上下班打卡时间范围不能为空，请检查项目设置");
        }*/

        // 如果签卡时间范围不为空，做时间范围的效验
        if (StrUtil.isNotBlank(crmProject.getSignInBegin()) && StrUtil.isNotBlank(crmProject.getSignInEnd())) {
            // 检查打卡时间，是否在设置的打卡范围内
            // 打卡开始时间
            DateTime signInBegin = DateUtil.parse(DateUtil.today() + " " + crmProject.getSignInBegin(), DatePattern.NORM_DATETIME_PATTERN);
            // 打卡结束时间
            DateTime signInEnd = DateUtil.parse(DateUtil.today() + " " + crmProject.getSignInEnd(), DatePattern.NORM_DATETIME_PATTERN);

            if (DateUtil.between(signInBegin, signInEnd, DateUnit.MS, Boolean.FALSE) < 1) {
                signInEnd = DateUtil.offsetDay(signInEnd, 1);
            }

            if (DateUtil.isIn(crmCustomerSignIn.getSignInTime(), signInBegin, signInEnd)) {
                logger.info("签卡ID：{}，签卡时间：{}，验证通过。", crmCustomerSignIn.getId(), DateUtil.format(crmCustomerSignIn.getSignInTime(), DatePattern.NORM_DATETIME_PATTERN));
            } else {
                throw new UtilException("打卡时间有误");
            }
        }


        // 查询工地
        CrmWorksite crmWorksite = crmWorksiteService.selectCrmWorksiteById(crmProject.getWorksiteId());

        // 设置工人关联的项目
        CrmCustomerProject crmCustomerProject = new CrmCustomerProject();
        crmCustomerProject.setCustomerId(crmCustomerSignIn.getCustomerId());
        crmCustomerProject.setMchId(crmCustomerSignIn.getMchId());
        crmCustomerProject.setEmployeeId(crmProject.getEmployeeId());
        if (crmWorksite != null) {
            crmCustomerProject.setWorksiteId(crmWorksite.getId());
            crmCustomerSignIn.setWorksiteId(crmWorksite.getId());
        }
        crmCustomerProject.setProjectId(crmProject.getId());
        ThreadUtil.execAsync(() -> crmCustomerProjectService.insertCrmCustomerProject(crmCustomerProject));

        // 项目负责人ID
        crmCustomerSignIn.setEmployeeId(crmProject.getEmployeeId());
        crmCustomerSignIn.setStatus(CrmCustomerSignIn.STATUS_AUDIT);
    }

    /**
     * 修改客户签卡记录
     *
     * @param crmCustomerSignIn 客户签卡记录
     * @return 结果
     */
    @Override
    public int updateCrmCustomerSignIn(CrmCustomerSignIn crmCustomerSignIn) {
        crmCustomerSignIn.setUpdateTime(DateUtils.getNowDate());
        return crmCustomerSignInMapper.updateCrmCustomerSignIn(crmCustomerSignIn);
    }

    /**
     * 批量删除客户签卡记录
     *
     * @param ids 需要删除的客户签卡记录主键
     * @return 结果
     */
    @Override
    public int deleteCrmCustomerSignInByIds(Long[] ids) {
        return crmCustomerSignInMapper.deleteCrmCustomerSignInByIds(ids);
    }

    /**
     * 删除客户签卡记录信息
     *
     * @param id 客户签卡记录主键
     * @return 结果
     */
    @Override
    public int deleteCrmCustomerSignInById(Long id) {
        return crmCustomerSignInMapper.deleteCrmCustomerSignInById(id);
    }

    /**
     * 签卡审批通过
     * @param id
     * @return
     */
    @Override
    @Transactional
    public int audits(Long id) {
        CrmCustomerSignIn crmCustomerSignIn = selectCrmCustomerSignInById(id);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        // 获取项目
        CrmProject crmProject = crmProjectService.selectCrmProjectById(crmCustomerSignIn.getProjectId());

        // 获取所有待审批签卡数据
        CrmCustomerSignIn query = new CrmCustomerSignIn();
        if (!(adminManager.loginUserIsAdminDept(loginUser) || adminManager.loginUserIsLeader(loginUser))) {
            query.setEmployeeId(loginUser.getUserId());
        }
        query.setStatus(CrmCustomerSignIn.STATUS_AUDIT);
        query.setProjectId(crmCustomerSignIn.getProjectId());
        List<CrmCustomerSignIn> crmCustomerSignIns = selectCrmCustomerSignInList(query);

        // List转Map
        Map<Long, List<CrmCustomerSignIn>> maps = crmCustomerSignIns.stream().collect(Collectors.groupingBy(CrmCustomerSignIn::getCustomerId));

        List<Long> auditList = new ArrayList<>();

        for (Map.Entry<Long, List<CrmCustomerSignIn>> entry : maps.entrySet()) {
            // 打卡时间排序
            List<CrmCustomerSignIn> newList =
                    entry.getValue().stream().sorted(Comparator.comparing(CrmCustomerSignIn::getSignInTime)).collect(Collectors.toList());
            logger.info("打开开始时间：{}", newList.get(0).getSignInTime());
            logger.info("打开开始结束：{}", newList.get(newList.size()-1).getSignInTime());

            // 如果开始时间和结束时间相等，跳过本条记录
            if (DateUtil.compare(newList.get(0).getSignInTime(), newList.get(newList.size()-1).getSignInTime()) == 0) {
                continue;
            }

            // 打卡数据，转写到薪资记录表
            CrmCustomerSalary customerSalary = new CrmCustomerSalary();
            customerSalary.setMchId(newList.get(0).getMchId());
            customerSalary.setCustomerId(newList.get(0).getCustomerId());
            customerSalary.setSignInStartTime(newList.get(0).getSignInTime());
            customerSalary.setSignInEndTime(newList.get(newList.size()-1).getSignInTime());
            long minute = DateUtil.between(customerSalary.getSignInStartTime(), customerSalary.getSignInEndTime(), DateUnit.MINUTE);
            long second = DateUtil.between(customerSalary.getSignInStartTime(), customerSalary.getSignInEndTime(), DateUnit.SECOND);
            customerSalary.setWorkDuration(LocalTime.ofSecondOfDay(second).format(DateTimeFormatter.ofPattern("HH:mm:ss")));
            customerSalary.setWorkSecond(second);
            customerSalary.setWorkMinute(minute);
            customerSalary.setSalaryUnit(crmProject.getSalaryUnit());
            customerSalary.setSalaryRate(crmProject.getSalaryRate());
            customerSalary.setHourlyRateCalculation(crmProject.getHourlyRateCalculation());
            customerSalary.setWorksiteId(crmProject.getWorksiteId());
            customerSalary.setProjectId(crmProject.getId());
            customerSalary.setResponsiblePersonId(crmProject.getEmployeeId());
            customerSalary.setSalaryAmount(BigDecimal.ZERO);
            customerSalary.setAuditStatus(CrmCustomerSalary.AUDIT_STATUS_AUDIT);
            customerSalary.setPaymentStatus(CrmCustomerSalary.PAYMENT_STATUS_NO_SETTLE);
            crmCustomerSalaryService.insertCrmCustomerSalary(customerSalary);
            // 处理的数据，放到集合中，准备修改审批状态
            List<Long> ids = newList.stream().map(CrmCustomerSignIn::getId).collect(Collectors.toList());
            auditList.addAll(ids);
        }
        if (auditList.size() > 0) {
            return crmCustomerSignInMapper.audits(auditList.toArray(new Long[auditList.size()]));
        } else {
            throw new UtilException("暂无可审核考勤，请确上下班考勤是否都正常");
        }
    }

    /**
     * 计算薪资
     * @param ids
     * @return
     */
    @Override
    public int settle(Long[] ids) {
        // 根据ID，查询出所有的记录
        List<CrmCustomerSignIn> list = crmCustomerSignInMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list)) {
            throw new UtilException("请先选择有效的记录后，再开始计算薪资");
        }
        Map<Long, CrmProject> projectMap = new HashMap<>();
        // 计算工作时长
        list.parallelStream().forEach(crmCustomerSignIn -> {
            // 获取项目，缓存中如果不存在，就去数据库拉取
            CrmProject crmProject = projectMap.get(crmCustomerSignIn.getProjectId());
            if (crmProject == null) {
                crmProject = crmProjectService.selectCrmProjectById(crmCustomerSignIn.getProjectId());
                if (crmProject == null) {
                    throw new UtilException("当前项目不存在");
                }
                projectMap.put(crmProject.getId(), crmProject);
            }

            // 根据薪资单位和时薪计算方式，计算薪资金额，并写入到客户薪资记录表（月薪、日薪不参与薪资计算）
            if (StrUtil.isBlank(crmProject.getSalaryUnit()) || !CrmProject.SALARY_UNIT_HOUR.equals(crmProject.getSalaryUnit())) {
                // 计算薪资
            }
        });

        // 根据薪资单位和时薪计算方式，计算薪资金额，并写入到客户薪资记录表（月薪、日薪不参与薪资计算）
        // TODO 待实现
        return 0;
    }

    /**
     * 根据客户查询签卡明细
     * @param crmCustomerSignIn
     * @return
     */
    @Override
    public List<CrmCustomerSignIn> findByUser(CrmCustomerSignIn crmCustomerSignIn) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        CrmCustomer customer = crmCustomerService.selectCrmCustomerByMemberId(crmCustomerSignIn.getMchId(), loginUser.getUserId());
        if (customer == null) {
            throw new UtilException("客户信息有误");
        }
        crmCustomerSignIn.setCustomerId(customer.getId());
        List<CrmCustomerSignIn> crmCustomerSignIns = crmCustomerSignInMapper.selectCrmCustomerSignInList(crmCustomerSignIn);
        if (CollUtil.isNotEmpty(crmCustomerSignIns)) {
            crmCustomerSignIns.parallelStream().forEach(c -> c.setCustomerName(customer.getCustomerName()));
        }
        return crmCustomerSignIns;
    }
}
